/***
 * @Description: 本文件是关于ARP协议的相关数据结构定义和具体协议功能实现的C语言文件
 * @Author: Liverpool
 * @Date: 2024-06-06 00:51:15
 * @LastEditTime: 2024-06-06 00:51:42
 * @LastEditors: Liverpool
 */
#include "arp.h"
#include "debug.h"
#include "tools.h"
#include "protocol.h"
#include "timer.h"
#include "ipv4.h"

#define time_to_scan_cnt(ms) (ms / ARP_TIMER_MS) // 时间和扫描周期之间的转化
// ---------------------------------变量定于区-------------------------------
static D_Net_timer arp_cache_timer;                       // ARP缓存表的计时器，进行定时检测ARP表项
static D_ARP_Entry arp_cache_table[ARP_CACHE_SIZE];       // 定义arp缓存表的数据存储区
static D_MemoryBlock arp_cache_mblock;                    // arp缓存表的内存管理模块
static D_List arp_cache_list;                             // arp缓存表的链表，最新使用的表项在前面
static const uint8_t empty_hwaddr[] = {0, 0, 0, 0, 0, 0}; // 定义空的MAC地址
// ---------------------------------函数定义区-------------------------------

#if Debug_Display_Enable(Debug_ARP)

/***
 * @description: (静态函数)打印ARP缓存表中的表项
 * @Author: Liverpool
 * @Date: 2024-06-14 02:30:07
 * @return {*}
 * @param {D_ARP_Entry} *entry 需要打印的表项
 */
static void arp_entry_display(D_ARP_Entry *entry)
{
    plat_printf("%d:", (int)(entry - arp_cache_table)); // 得到索引
    debug_dump_ipaddr_buf("\tIP:", entry->ipaddr);
    debug_dump_hwaddr("\t mac:", entry->hwaddr, ETHERNET_HW_SIZE);
    plat_printf("\tms:%d, retry:%d, state:%s, buf:%d\n", entry->ms, entry->retry, entry->state == NET_ARP_RESOLVED ? "stable" : "pending", list_get_count(&entry->buf_list));
}
/***
 * @description: (静态函数)打印展示ARP包的缓存表
 * @Author: Liverpool
 * @Date: 2024-06-14 02:27:07
 * @return {*}
 */
static void arp_cache_table_display(void)
{
    plat_printf("-------------------arp table start------------------------\n");
    D_ARP_Entry *entry = arp_cache_table;
    for (int i = 0; i < ARP_CACHE_SIZE; i++, entry++)
    {
        // NET_ARP_FREE 不打印
        if ((entry->state != NET_ARP_WAITING) && (entry->state != NET_ARP_RESOLVED))
        {
            continue;
        }
        arp_entry_display(entry);
    }
    plat_printf("-------------------arp table end------------------------\n");
}
/***
 * @description: (静态函数)对ARP数据包进行解析和打印
 * @Author: Liverpool
 * @Date: 2024-06-13 23:12:44
 * @return {*}
 * @param {D_ARP_Packet} *packet 需要打印和解析的数据包
 */
static void arp_packet_display(D_ARP_Packet *packet)
{
    uint16_t operation_code = x_ntohs(packet->operation_code);
    plat_printf("-------------------arp packet------------------------\n");
    plat_printf("\thw_type:%d\n", x_ntohs(packet->hw_type));
    plat_printf("\tprotocol_type:%04x\n", x_ntohs(packet->protocol_type));
    plat_printf("\thw_len:%d\n", packet->hw_len);
    plat_printf("\tprotocol_len:%d\n", packet->protocol_len);
    plat_printf("\topreation_code:%d;", operation_code);
    switch (operation_code)
    {
    case ARP_REQUEST:
        plat_printf("request\n");
        break;
    case ARP_REPLY:
        plat_printf("replay\n");
        break;
    default:
        plat_printf("unknown\n");
        break;
    }
    debug_dump_ipaddr_buf("\tsender:", packet->send_ipaddr);
    debug_dump_hwaddr("\tmac:", packet->send_hwaddr, ETHERNET_HW_SIZE);
    debug_dump_ipaddr_buf("\n\ttarget:", packet->target_ipaddr);
    debug_dump_hwaddr("\tmac:", packet->target_hwaddr, ETHERNET_HW_SIZE);
    plat_printf("\n-------------------arp end------------------------\n");
}
#else
#define arp_packet_display(packet)
#define arp_cache_table_display()
#define arp_entry_display(entry)
#endif

/***
 * @description: (静态函数)ARP协议的缓存表进行初始化
 * @Author: Liverpool
 * @Date: 2024-06-06 02:49:39
 * @return {*} 缓存表初始化过程中的错误
 */
static net_err_t arp_cache_init(void)
{
    list_init(&arp_cache_list);

    net_err_t err = memory_block_init(&arp_cache_mblock, arp_cache_table, sizeof(D_ARP_Entry), ARP_CACHE_SIZE, Locker_Self);
    if (err < 0)
    {
        return err;
    }
    return NET_ERR_OK;
}

/***
 * @description: (静态函数)对缓存表的表项进行数据包清除
 * @Author: Liverpool
 * @Date: 2024-06-15 14:33:49
 * @return {*}
 * @param {D_ARP_Entry} *entry 需要清除数据包的表项的内存地址
 */
static void arp_cache_enty_data_clear(D_ARP_Entry *entry)
{
    debug_info(Debug_ARP, "cache entry clear packet...\n");
    D_ListNode *first;
    while ((first = list_remove_first(&entry->buf_list)))
    {
        D_Packet *buf = list_entry(first, D_Packet, node);
        packet_free(buf);
    }
}

/***
 * @description: (静态函数)对缓存表中的表项的所有数据包进行发送出去
 * @Author: Liverpool
 * @Date: 2024-06-16 16:16:25
 * @return {*} 发送过程中出现的错误
 * @param {D_ARP_Entry} *entry 需要进行发送的缓存表项
 */
static net_err_t arp_cache_entry_data_send(D_ARP_Entry *entry)
{
    debug_info(Debug_ARP, "cache entry send packet...\n");
    if (Debug_ARP >= D_DEBUG_Level_Info)
    {
        debug_dump_ipaddr_buf("ip:", entry->ipaddr);
    }
    D_ListNode *first;
    while ((first = list_remove_first(&entry->buf_list)))
    {
        D_Packet *buf = list_entry(first, D_Packet, node);
        net_err_t err = ethernet_raw_out(entry->netif, Net_Protocol_IPv4, entry->hwaddr, buf);
        if (err < 0)
        {
            packet_free(buf);
        }
    }
    return NET_ERR_OK;
}

/***
 * @description:  (静态函数)ARP缓存表分配一个表项缓存空间
 * @Author: Liverpool
 * @Date: 2024-06-15 13:52:54
 * @return {*} 分配到的表项内存空间
 * @param {int} force_mode 是否开启强制分配模式 1:强制分配开启  0:强制分配关闭
 */
static D_ARP_Entry *arp_cache_entry_alloc(int force_mode)
{
    D_ARP_Entry *entry = memory_block_alloc(&arp_cache_mblock, -1); // 分配一个表项内存空间
    if (!entry && force_mode)
    {
        // 如果内存管理模块没有足够的内存空间进行分配并且开启强制分配模式，那就直接从ARP缓存表移除最后一个节点最为新节点进行分配
        D_ListNode *node = list_remove_last(&arp_cache_list);
        if (!node)
        {
            debug_error(Debug_ARP, "arp cache entry alloc failed...");
            return (D_ARP_Entry *)0;
        }
        entry = list_entry(node, D_ARP_Entry, node); // 找到最后一个节点的ARP表项
        arp_cache_enty_data_clear(entry);            // 对表项的数据包节点进行清除释放
    }
    if (entry)
    {
        plat_memset(entry, 0, sizeof(D_ARP_Entry));
        entry->state = NET_ARP_FREE; // 设置该表项的状态为未分配
        // 对表项的节点和数据包节点进行初始化
        list_node_init(&entry->node);
        list_init(&entry->buf_list);
    }
    else
    {
        debug_error(Debug_ARP, "arp cache entry alloc failed...");
        return (D_ARP_Entry *)0;
    }
    return entry;
}

/***
 * @description: (静态函数)对ARP缓存表中的表项进行释放回收
 * @Author: Liverpool
 * @Date: 2024-06-15 14:43:44
 * @return {*}
 * @param {D_ARP_Entry} *entry 需要进行释放回收的表项内存地址
 */
static void arp_cache_entry_free(D_ARP_Entry *entry)
{
    arp_cache_enty_data_clear(entry);                // 释放表项的数据包
    list_remove_node(&arp_cache_list, &entry->node); // 从链表中移除该表项节点
    memory_block_free(&arp_cache_mblock, entry);     // 回收该表项的内存空间
}

/***
 * @description: (静态函数)在ARP缓存表中查找对应的IP地址所拥有的表项
 * @Author: Liverpool
 * @Date: 2024-06-16 14:53:33
 * @return {*} 查找到的缓存表项
 * @param {uint8_t} ipaddr 需要查找的IP地址
 */
static D_ARP_Entry *arp_cache_find_entry(uint8_t *ipaddr)
{
    D_ListNode *node;
    list_for_each_node(node, &arp_cache_list)
    {
        D_ARP_Entry *entry = list_entry(node, D_ARP_Entry, node);
        if (plat_memcmp(ipaddr, entry->ipaddr, IPV4_ADDR_SIZE) == 0)
        {
            // 如果找到对应的IP地址表项，最好还需要把该表项移动到链表的头部
            list_remove_node(&arp_cache_list, &entry->node);
            list_insert_first(&arp_cache_list, &entry->node);
            return entry;
        }
    }
    return (D_ARP_Entry *)0;
}

/***
 * @description: (静态函数)给缓存表的表项设置参数
 * @Author: Liverpool
 * @Date: 2024-06-16 15:57:17
 * @return {*}
 * @param {D_ARP_Entry} *entry 需要设置的表项
 * @param {uint8_t} *hw_addr mac地址
 * @param {uint8_t} *ip_addr ip地址
 * @param {D_Net_Interface} *netif 链接的网卡
 * @param {int} state 表项的状态
 */
static void arp_cache_entry_set(D_ARP_Entry *entry, const uint8_t *hw_addr, uint8_t *ip_addr, D_Net_Interface *netif, int state)
{
    plat_memcpy(entry->hwaddr, hw_addr, ETHERNET_HW_SIZE);
    plat_memcpy(entry->ipaddr, ip_addr, IPV4_ADDR_SIZE);
    entry->state = state;
    entry->netif = netif;
    // 根据ARP表项的不同状态来设置等待时间
    if (state == NET_ARP_RESOLVED)
    {
        entry->ms = time_to_scan_cnt(ARP_ENTRY_STABLE_MS);
    }
    else
    {
        entry->ms = time_to_scan_cnt(ARP_ENTRY_PENDING_MS);
    }
    entry->retry = ARP_ENTRY_RETRY_CNT;
}

/***
 * @description: (静态函数)在ARP缓存表中插入新的表项
 * @Author: Liverpool
 * @Date: 2024-06-16 02:01:42
 * @return {*} 在插入缓存表的过程中出现的错误
 * @param {D_Net_Interface} *netif 网卡接口内存地址
 * @param {uint8_t} *ip_addr 需要插入的表项的IP地址
 * @param {uint8_t} *hw_addr 需要插入的表项的MAC地址
 * @param {int} force_mode 表项强制分配模式 1:开启  0:关闭
 */
static net_err_t arp_cache_insert(D_Net_Interface *netif, uint8_t *ip_addr, uint8_t *hw_addr, int force_mode)
{
    if (*(uint32_t *)ip_addr == 0)
    {
        return NET_ERR_NOT_SUPPORT;
    }
    D_ARP_Entry *entry = arp_cache_find_entry(ip_addr); // 根据IP地址查找缓存表中的相应表项
    if (!entry)
    {
        // 在其中没有找到对应IP地址的表项，那就需要分配相应的表项
        entry = arp_cache_entry_alloc(force_mode);
        if (!entry)
        {
            if (Debug_ARP >= D_DEBUG_Level_Info)
            {
                debug_dump_ipaddr_buf("arp cache enrty alloc failed, ip:", ip_addr);
            }
            return NET_ERR_NONE;
        }
        arp_cache_entry_set(entry, hw_addr, ip_addr, netif, NET_ARP_RESOLVED); // 设置ARP表项的状态
        list_insert_first(&arp_cache_list, &entry->node);                      // 把新分配的节点插入到链表的最前面
    }
    else
    {
        if (Debug_ARP >= D_DEBUG_Level_Info)
        {
            debug_dump_ipaddr_buf("arp cache update entry, ip:", ip_addr);
        }
        arp_cache_entry_set(entry, hw_addr, ip_addr, netif, NET_ARP_RESOLVED); // 设置ARP表项的状态
        if (list_get_first(&arp_cache_list) != &entry->node)
        {
            // 如果不是链表的头结点表项，那就需要插入到arp链表的头结点
            list_remove_node(&arp_cache_list, &entry->node);
            list_insert_first(&arp_cache_list, &entry->node);
        }
        // 需要把之前可能由于mac地址错误，而未发出的数据包需要进行发送出去
        net_err_t err = arp_cache_entry_data_send(entry);
        if (err < 0)
        {
            debug_error(Debug_ARP, "arp cache enrty send packet failid...");
            return err;
        }
    }
    arp_cache_table_display();
    return NET_ERR_OK;
}

/***
 * @description: (静态函数)ARP缓存表的定时器扫描周期函数
 * @Author: Liverpool
 * @Date: 2024-06-18 00:39:27
 * @return {*}
 * @param {D_Net_timer} *timer
 * @param {void} *arg
 */
static void arp_cache_timer_func(D_Net_timer *timer, void *arg)
{
    D_ListNode *curr, *next;
    int change_cnt = 0; // 改变的arp表项个数
    // 遍历整个ARP缓存表
    for (curr = list_get_first(&arp_cache_list); curr; curr = next)
    {
        next = list_node_get_next(curr);
        D_ARP_Entry *entry = list_entry(curr, D_ARP_Entry, node);
        if (--entry->ms > 0)
        {
            // 现在ARP表项的超时时间还没有到
            continue;
        }
        change_cnt++;
        // 对到达时间的ARP缓存表项进行处理
        switch (entry->state)
        {
        case NET_ARP_RESOLVED:
            // 如果该表项是处于稳定状态,就需要重现发送ARP请求，来更新缓存表项的数据
            debug_info(Debug_ARP, "arp entry state from stable to pending:");
            arp_entry_display(entry);
            D_IP_ADDR ip_addr;
            ipaddr_from_buf(&ip_addr, entry->ipaddr);
            entry->state = NET_ARP_WAITING; // 改变表项的状态
            entry->ms = time_to_scan_cnt(ARP_ENTRY_PENDING_MS);
            entry->retry = ARP_ENTRY_RETRY_CNT;
            arp_make_request(entry->netif, &ip_addr); // 重新发送ARP请求
            break;
        case NET_ARP_WAITING:
            // 该表项处于等待状态，需要检查是否重连次数为0
            if (--entry->retry == 0)
            {
                debug_info(Debug_ARP, "arp entry pending tmo, need to free it...");
                arp_entry_display(entry);
                arp_cache_entry_free(entry); // 重连次数超时需要释放该表项
            }
            else
            {
                // arp表项的重连次数没有为0，那就需要进行重新发送arp请求
                debug_info(Debug_ARP, "arp entry pending tmo, need to send resquest...");
                arp_entry_display(entry);
                D_IP_ADDR ip_addr;
                ipaddr_from_buf(&ip_addr, entry->ipaddr);
                entry->ms = time_to_scan_cnt(ARP_ENTRY_PENDING_MS);
                arp_make_request(entry->netif, &ip_addr); // 重新发送ARP请求
            }
            break;
        default:
            debug_error(Debug_ARP, "arp entry state state Unknown");
            arp_entry_display(entry);
            break;
        }
    }
    if (change_cnt)
    {
        debug_info(Debug_ARP, "%d arp entry have changed", change_cnt);
        arp_cache_table_display();
    }
}

/***
 * @description: ARP协议的模块初始化
 * @Author: Liverpool
 * @Date: 2024-06-06 00:53:29
 * @return {*} 返回初始化过程中的错误
 */
net_err_t arp_init(void)
{
    net_err_t err = arp_cache_init();
    if (err < 0)
    {
        debug_error(Debug_ARP, "ARP Cache init fail...");
        return err;
    }
    // 对ARP缓存表的定时器进行初始化
    err = net_timer_add(&arp_cache_timer, "arp timer", arp_cache_timer_func, (void *)0, ARP_TIMER_MS * 1000, NET_TIMER_RELOAD);
    if (err < 0)
    {
        debug_error(Debug_ARP, "ARP Cache create timer fail: %d", err);
        return err;
    }
    return NET_ERR_OK;
}

/***
 * @description: 进行ARP协议的请求，进行ARP请求包的发送
 * @Author: Liverpool
 * @Date: 2024-06-07 01:06:41
 * @return {*} 发送过程中出现的错误
 * @param {D_Net_Interface} *netif 需要发送的网卡内存地址
 * @param {D_IP_ADDR} *dest 需要进行ARP请求的IP地址
 */
net_err_t arp_make_request(D_Net_Interface *netif, const D_IP_ADDR *dest)
{
    // 1.分配相应的ARP请求的数据包
    D_Packet *buf = packet_alloc(sizeof(D_ARP_Packet));
    if (buf == (D_Packet *)0)
    {
        debug_error(Debug_ARP, "ARP alloc packet failed...");
        return NET_ERR_NONE;
    }
    // 2.对分配的数据包进行连续化处理和数据解析定位
    packet_set_continuous(buf, sizeof(D_ARP_Packet));
    D_ARP_Packet *arp_packet = (D_ARP_Packet *)packet_firstBlock_data(buf);
    // 3.对ARP协议的数据包进行内容的填充
    arp_packet->hw_type = x_htons(ARP_HW_ETHERNET);
    arp_packet->protocol_type = x_htons(Net_Protocol_IPv4);
    arp_packet->hw_len = ETHERNET_HW_SIZE;
    arp_packet->protocol_len = IPV4_ADDR_SIZE;
    arp_packet->operation_code = x_htons(ARP_REQUEST);
    plat_memcpy(arp_packet->send_hwaddr, netif->hwaddr.address, ETHERNET_HW_SIZE);
    ipaddr_to_buf(&netif->ipaddr, arp_packet->send_ipaddr);
    plat_memset(arp_packet->target_hwaddr, 0, ETHERNET_HW_SIZE);
    ipaddr_to_buf(dest, arp_packet->target_ipaddr);
    arp_packet_display(arp_packet);
    // 4.使用以太网协议把ARP请求的数据包发送出去
    net_err_t err = ethernet_raw_out(netif, Net_Protocol_ARP, ethernet_broadcast_addr(), buf); // 广播ARP请求,以太网会自动补充相应的以太网帧头
    if (err < 0)                                                                               // 出错就在本层释放数据包，否则就就给下层协议进行释放
    {
        packet_free(buf);
    }
    return err;
}

/***
 * @description: ARP协议对请求做出回应
 * @Author: Liverpool
 * @Date: 2024-06-10 22:14:35
 * @return {*} 在回应过程中出现的错误
 * @param {D_Net_Interface} *netif 网卡内存地址
 * @param {D_Packet} *buf 接收到的数据包
 */
net_err_t arp_make_reply(D_Net_Interface *netif, D_Packet *buf)
{
    D_ARP_Packet *arp_packet = (D_ARP_Packet *)packet_firstBlock_data(buf); // 对数据包做ARP协议分解
    arp_packet->operation_code = x_htons(ARP_REPLY);                        // 变成回应操作码
    // 从原数据包中获取目标地址并且进行对原数据包的数据改写
    plat_memcpy(arp_packet->target_hwaddr, arp_packet->send_hwaddr, ETHERNET_HW_SIZE);
    plat_memcpy(arp_packet->target_ipaddr, arp_packet->send_ipaddr, IPV4_ADDR_SIZE);
    plat_memcpy(arp_packet->send_hwaddr, netif->hwaddr.address, ETHERNET_HW_SIZE);
    ipaddr_to_buf(&netif->ipaddr, arp_packet->send_ipaddr);
    arp_packet_display(arp_packet);
    //  发送改写后的数据包
    return ethernet_raw_out(netif, Net_Protocol_ARP, arp_packet->target_hwaddr, buf);
}

/***
 * @description: 广播一个免费(无回报的)ARP包(主机接入网络的时候需要，告诉其他主机自己的MAC地址和IP地址)
 * @Author: Liverpool
 * @Date: 2024-06-09 10:04:51
 * @return {*}
 * @param {D_Net_Interface} *netif 发送的网卡
 */
net_err_t arp_make_gratuitous(D_Net_Interface *netif)
{
    debug_info(Debug_ARP, "send an gratuitous arp ....");
    return arp_make_request(netif, &netif->ipaddr);
}

/***
 * @description: (静态函数)对ARP数据包是否合法进行校验
 * @Author: Liverpool
 * @Date: 2024-06-09 21:19:38
 * @return {*}  是否合法 0:合法  <0:不合法
 * @param {D_ARP_Packet} *arp_packet 需要校验的ARP数据包内存地址
 * @param {uint16_t} size 数据包的长度
 * @param {D_Net_Interface} *netif 接收数据包的网卡内存地址
 */
static net_err_t is_ARP_packet_ok(D_ARP_Packet *arp_packet, uint16_t size, D_Net_Interface *netif)
{
    // 1.首先需要对数据包的长度进行判断
    if (size < sizeof(D_ARP_Packet))
    {
        debug_Warning(Debug_ARP, "packet size err!");
        return NET_ERR_SIZE;
    }
    // 2.需要对数据包的硬件协议和IP协议进行判断,目前本协议栈只支持Ethernet和IPv4
    if ((x_ntohs(arp_packet->hw_type) != ARP_HW_ETHERNET) || (arp_packet->hw_len != ETHERNET_HW_SIZE) || (x_ntohs(arp_packet->protocol_type) != Net_Protocol_IPv4) || (arp_packet->protocol_len != IPV4_ADDR_SIZE))
    {
        debug_Warning(Debug_ARP, "packet incorrect...");
        return NET_ERR_NOT_SUPPORT;
    }
    // 3.对数据包的操作码进行判断
    uint16_t operation_code = x_ntohs(arp_packet->operation_code);
    if ((operation_code != ARP_REPLY) && (operation_code != ARP_REQUEST))
    {
        debug_Warning(Debug_ARP, "unkonwn operation code...");
        return NET_ERR_NOT_SUPPORT;
    }
    return NET_ERR_OK;
}

/***
 * @description: 对输入的ARP数据包进行数据解析
 * @Author: Liverpool
 * @Date: 2024-06-09 19:37:04
 * @return {*} ARP数据包是否合法和解析过程中出现的错误
 * @param {D_Net_Interface} *netif 解析数据包的网卡内存地址
 * @param {D_Packet} *buf 需要进行解析的数据包
 */
net_err_t arp_in(D_Net_Interface *netif, D_Packet *buf)
{
    debug_info(Debug_ARP, "arp in...");
    net_err_t err = packet_set_continuous(buf, sizeof(D_ARP_Packet));
    if (err < 0)
    {
        return err;
    }
    D_ARP_Packet *arp_packet = (D_ARP_Packet *)packet_firstBlock_data(buf); // 对数据包做ARP协议分解
    if ((err = is_ARP_packet_ok(arp_packet, buf->total_size, netif)) != NET_ERR_OK)
    {
        return err;
    }
    // TODO:
    // 对ARP数据包进行解析处理
    arp_packet_display(arp_packet);
    D_IP_ADDR target_ip;
    ipaddr_from_buf(&target_ip, arp_packet->target_ipaddr);
    if (ipaddr_is_equal(&netif->ipaddr, &target_ip))
    {
        // ARP协议的发送地址和本网络接口的IP地址相同，就进行数据解析
        debug_info(Debug_ARP, "receive an arp packet for me...");
        arp_cache_insert(netif, arp_packet->send_ipaddr, arp_packet->send_hwaddr, ARP_CACHE_ALLOC_FORCE); // 对ARP数据包进行解析后插入到表项中去
        if (x_ntohs(arp_packet->operation_code) == ARP_REQUEST)
        {
            debug_info(Debug_ARP, "arp request, send reply...");
            return arp_make_reply(netif, buf);
        }
    }
    else
    {
        // 其他计算机启动的时候发送的无回应的免费包，如果有空闲的表项就更新一下，没有就算了
        debug_info(Debug_ARP, "receive an arp packet,not for me...");
        arp_cache_insert(netif, arp_packet->send_ipaddr, arp_packet->send_hwaddr, ARP_CACHE_ALLOC_UNFORCE); // 对ARP数据包进行解析后插入到表项中去
    }
    packet_free(buf);
    return NET_ERR_OK;
}

/***
 * @description: ARP协议的解析函数(进行在ARP缓存表中查询相应的IP地址寻找MAC地址，找到就直接发送；没有找到就发送ARP请求，查找MAC地址，并把数据包插入到数据包链表中)
 * @Author: Liverpool
 * @Date: 2024-06-16 19:58:16
 * @return {*} 在处理过程中出现的错误
 * @param {D_Net_Interface} *netif 需要发送的网卡
 * @param {D_IP_ADDR} *ipaddr 需要解析和发送的IP地址
 * @param {D_Packet} *buf 需要发送的数据包
 */
net_err_t arp_resolve(D_Net_Interface *netif, const D_IP_ADDR *ipaddr, D_Packet *buf)
{
    D_ARP_Entry *entry = arp_cache_find_entry((uint8_t *)ipaddr->a_addr); // 查找有无ARP缓存表
    if (entry)
    {
        // 找到对应IP地址的ARP缓存表表项
        debug_info(Debug_ARP, "find the arp entry...");
        if (entry->state == NET_ARP_RESOLVED) // 如果该表项处于已经解析完成的状态，那就直接发送数据包
        {
            return ethernet_raw_out(netif, Net_Protocol_IPv4, entry->hwaddr, buf);
        }
        // 如果还处于解析等待回应的情况下，需要根据该表项的数据包链表的发送的等待数量做出处理
        if (list_get_count(&entry->buf_list) <= ARP_MAX_Packet_Wait)
        {
            debug_info(Debug_ARP, "insert wait packet to arp cache entry...");
            list_insert_last(&entry->buf_list, &buf->node); // 插入在表项数据链表的最后
            return NET_ERR_OK;
        }
        else // 等待发送的数据包太多了
        {
            debug_Warning(Debug_ARP, "too many waiting packet in arp cache entry...");
            return NET_ERR_FULL;
        }
    }
    else // 没有找到该缓存表项
    {
        debug_info(Debug_ARP, "make an arp request...");
        entry = arp_cache_entry_alloc(ARP_CACHE_ALLOC_FORCE); // 分配一个ARP缓存表项
        if (entry == (D_ARP_Entry *)0)
        {
            debug_error(Debug_ARP, "arp cache entry alloc failed...");
            return NET_ERR_NONE;
        }
        arp_cache_entry_set(entry, empty_hwaddr, (uint8_t *)ipaddr->a_addr, netif, NET_ARP_WAITING); // 设置该表项的状态为等待回应状态
        list_insert_first(&arp_cache_list, &entry->node);                                            // 把新分配的表项插入到最前面
        list_insert_last(&entry->buf_list, &buf->node);                                              // 挂载数据包
        arp_cache_table_display();
        return arp_make_request(netif, ipaddr); // 发送ARP请求
    }
}

/***
 * @description: 对ARP缓存表进行清空
 * @Author: Liverpool
 * @Date: 2024-06-22 23:33:21
 * @return {*}
 * @param {D_Net_Interface} *netif 需要清空ARP表的指定网络接口的内存地址
 */
void arp_cache_clear(D_Net_Interface *netif)
{
    D_ListNode *node, *next;
    for (node = list_get_first(&arp_cache_list); node; node = next)
    {
        next = list_node_get_next(node);
        D_ARP_Entry *entry = list_entry(node, D_ARP_Entry, node);
        if (entry->netif == netif)
        {
            arp_cache_entry_free(entry); // 找到对应的网络接口以后就需要进行清除
        }
    }
}

/***
 * @description: 在arp缓存表中查找对应网卡的对应IP地址的MAC地址
 * @Author: Liverpool
 * @Date: 2024-06-24 02:35:03
 * @return {*} mac地址
 * @param {D_Net_Interface} *netif 对应的网卡内存地址
 * @param {D_IP_ADDR} *ipaddr 对应的IP地址
 */
const uint8_t *arp_find(D_Net_Interface *netif, D_IP_ADDR *ipaddr)
{
    // 根据IP地址是否本地广播或定向广播，来返回MAC地址的广播
    if (ipaddr_is_local_broadcast(ipaddr) || ipaddr_is_direct_broadcast(ipaddr, &netif->netmask))
    {
        return ethernet_broadcast_addr();
    }

    D_ARP_Entry *entry = arp_cache_find_entry(ipaddr->a_addr);
    if (entry && (entry->state == NET_ARP_RESOLVED))
    {
        // 如果在arp缓存表中找到该表项并且处于以解析的状态，那就直接返回其对应的MAC地址
        return entry->hwaddr;
    }
    return (const uint8_t *)0;
}

/***
 * @description: 从IP数据被中更新ARP缓存表
 * @Author: Liverpool
 * @Date: 2024-07-15 23:08:28
 * @return {*}
 * @param {D_Net_Interface} *netif 接收到IP数据报的网络接口
 * @param {D_Packet} *buf 接收到的IP数据报
 */
void arp_update_from_IP_packet(D_Net_Interface *netif, D_Packet *buf)
{
    net_err_t err = packet_set_continuous(buf, sizeof(D_IPv4_Header) + sizeof(D_Ethernet_Header)); // 设置包头的连续性
    if (err < 0)
    {
        debug_error(Debug_ARP, "adjust header failed...");
        return;
    }
    D_Ethernet_Header *ethernet_header = (D_Ethernet_Header *)packet_firstBlock_data(buf);                  // 获取以太网帧头内存地址
    D_IPv4_Header *ipv4_header = (D_IPv4_Header *)((uint8_t *)ethernet_header + sizeof(D_Ethernet_Header)); // 定位到IPv4的数据包头位置
    if (ipv4_header->version != NET_VERSION_IPV4)
    {
        debug_Warning(Debug_ARP, "not ipv4");
        return;
    }
    arp_cache_insert(netif, ipv4_header->src_ip, ethernet_header->src, 0); // 更新ARP缓存表
}